package cn.wj.school.server.net.ecode;

import cn.wj.school.common.dto.BaseMsg;
import cn.wj.school.common.manager.ManagerBuilder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;

/**
 * 消息解码
 */
public class MsgDecoder extends LengthFieldBasedFrameDecoder {

	public MsgDecoder(int maxFrameLength, int lengthFieldOffset,
					  int lengthFieldLength, int lengthAdjustment,
					  int initialBytesToStrip) {
		super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment,
				initialBytesToStrip);
	}

	@Override
	public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
		ByteBuf frame = (ByteBuf) super.decode(ctx, in);
		if (frame == null) {
			return null;
		}
		if(frame.readableBytes() <= 0) {
			return null;
		}

		int msgType = frame.readInt();
		BaseMsg msg = ManagerBuilder.getManagerBuilder().getBaseMsg(msgType);
		boolean useCompression = msg.isUseCompression();
		ByteBuf realBuf = decompression(frame,useCompression);
		msg.readBody(realBuf);

		return msg;
	}

	private ByteBuf decompression(ByteBuf sourceBuf, boolean useCompression) throws IOException{
		if(!useCompression){
			return sourceBuf;
		}

		//先读压缩数据的长度
		int bodyLength = sourceBuf.readInt();
		byte[] sourceBytes  = new byte[bodyLength];
		//得到压缩数据的字节数组
		sourceBuf.readBytes(sourceBytes);

		//解压缩
		ByteArrayInputStream bis = new ByteArrayInputStream(sourceBytes);
		GZIPInputStream gzip = new GZIPInputStream(bis);

		//假设压缩率最大为100%！！！！！
		byte[] content = new byte[bodyLength * 2];
		int num;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		while ((num = gzip.read(content, 0, content.length)) != -1) {
			baos.write(content, 0, num);
		}
		baos.flush();
		gzip.close();
		bis.close();

		//重新封装成ByteBuf对象
		ByteBuf resultBuf = Unpooled.buffer();
		//压缩前的实际数据
		byte[] realBytes = baos.toByteArray();
		resultBuf.writeBytes(realBytes);
		baos.close();

		return resultBuf;
	}

	public static void main(String[] args) {
		ManagerBuilder.getManagerBuilder();
	}
}
